package com.sc.nft.util;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.Header;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.sup.ErrorCode;
import lombok.experimental.UtilityClass;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@UtilityClass
public class BankCardUtil {


    private final Map<String,String> bankMapRelation = new HashMap<String,String>(){{
        put("ABC","农业银行");
        put("AHRCUB","安徽省农村信用社联合社");
        put("BCZ","沧州银行");
        put("BDB","保定银行");
        put("BEEB","鄞州银行");
        put("BGZB","贵州银行");
        put("BHB","河北银行");
        put("BJRCB","北京农商行");
        put("BNC","江西银行");
        put("BOB","北京银行");
        put("BJBANK","北京银行");
        put("BOBBG","北部湾银行");
        put("BOC","中国银行");
        put("BOCD","成都银行");
        put("BOCDB","承德银行");
        put("BOCTS","焦作中旅银行");
        put("BOD","东莞银行");
        put("BOFS","抚顺银行");
        put("BOHN","海南银行");
        put("BOIMCB","内蒙古银行");
        put("BOJN","济宁银行");
        put("BOJX","嘉兴银行");
        put("BOLB","洛阳银行");
        put("BOLFB","廊坊银行");
        put("BONX","宁夏银行");
        put("BOPDS","平顶山银行");
        put("BOQHB","青海银行");
        put("BOSH","上海银行");
        put("BOSXB","绍兴银行");
        put("BOSZS","石嘴山银行");
        put("BOTSB","唐山银行");
        put("BOZ","张家口银行");
        put("BSB","包商银行");
        put("BYK","营口银行");
        put("CBHB","渤海银行");
        put("CCAB","长安银行");
        put("CCB","建设银行");
        put("CDRCB","成都农商银行");
        put("CEB","光大银行");
        put("CIB","兴业银行");
        put("CITIB","花旗银行");
        put("CITIC","中信银行");
        put("CJCCB","江苏长江商业银行");
        put("CMB","招商银行");
        put("CMBC","民生银行");
        put("COMM","交通银行");
        put("CQB","重庆银行");
        put("CQRCB","重庆农商银行");
        put("CQTGB","重庆三峡银行");
        put("CRB","华润银行");
        put("CSCB","长沙银行");
        put("CSRCB","常熟农商银行");
        put("CYCB","朝阳银行");
        put("CZBANK","浙商银行");
        put("CZCB","稠州银行");
        put("DANDONGB","丹东银行");
        put("DLB","大连银行");
        put("DRCB","东莞农商银行");
        put("DYB","东营银行");
        put("DYCCB","长城华西银行");
        put("DZB","德州银行");
        put("FBB","富邦华一银行");
        put("FDB","富滇银行");
        put("FJHXB","福建海峡银行");
        put("FJNX","福建农信银行");
        put("FUXINB","阜新银行");
        put("GDB","广发银行");
        put("GDHX","广东华兴银行");
        put("JXRCU","江西省农村信用社联合社");
        put("GDRCC","广东省农村信用社联合社");
        put("GDNYB","南粤银行");
        put("GDRCU","广东农信银行");
        put("GRCB","广州农商银行");
        put("GSB","甘肃银行");
        put("GXNX","广西农信");
        put("GYCB","贵阳银行");
        put("GZCB","广州银行");
        put("GZCCB","赣州银行");
        put("GZNX","贵州农信");
        put("HAINNX","海南农信");
        put("HANAB","韩亚银行");
        put("HBCB","湖北银行");
        put("HBNX","湖北农信");
        put("HDCB","邯郸银行");
        put("HEBNX","河北农信");
        put("EGBANK","恒丰银行");
        put("HKB","汉口银行");
        put("HKBEA","东亚银行");
        put("HLDCCB","葫芦岛银行");
        put("HLJRCUB","黑龙江农信社");
        put("HNNX","河南农信");
        put("HRBANK","哈尔滨银行");
        put("HRXJB","华融湘江银行");
        put("HSB","徽商银行");
        put("HSBC","恒生银行");
        put("HSBCC","汇丰银行");
        put("HUNNX","湖南农信");
        put("HUSRB","湖商村镇银行");
        put("HXBANK","华夏银行");
        put("HZCB","杭州银行");
        put("HZCCB","湖州银行");
        put("ICBC","工商银行");
        put("JCB","晋城银行");
        put("JHCCB","金华银行");
        put("JJCCB","九江银行");
        put("JLB","吉林银行");
        put("JLNX","吉林农信");
        put("JNRCB","江南农商");
        put("JRCB","江阴农商行");
        put("JSB","江苏银行");
        put("JSHB","晋商银行");
        put("JSNX","江苏农信");
        put("JUFENGB","临朐聚丰村镇银行");
        put("JXNXB","江西农信");
        put("JZB","晋中银行");
        put("JZCB","锦州银行");
        put("KLB","昆仑银行");
        put("KRCB","昆山农商");
        put("KUERLECB","库尔勒市商业银行");
        put("LJB","龙江银行");
        put("LNNX","辽宁农信");
        put("LSB","临商银行");
        put("LSCCB","乐山市商业银行");
        put("LUZB","柳州银行");
        put("LWB","莱商银行");
        put("LYYHB","辽阳银行");
        put("LZB","兰州银行");
        put("LZCCB","泸州市商业银行");
        put("MINTAIB","民泰银行");
        put("NBCB","宁波银行");
        put("NCB","宁波通商银行");
        put("NCBCB","南洋商业银行");
        put("NCCB","四川天府银行");
        put("NJCB","南京银行");
        put("NMGNX","内蒙古农信");
        put("NYCCB","南阳村镇银行");
        put("ORDOSB","鄂尔多斯银行");
        put("PAB","平安银行");
        put("SPABANK","平安银行");
        put("PSBC","邮储银行");
        put("PZHCCB","攀枝花银行");
        put("QDCCB","青岛银行");
        put("QHDB","秦皇岛银行");
        put("QHNX","青海农信");
        put("QSB","齐商银行");
        put("QZCCB","泉州银行");
        put("RZB","日照银行");
        put("SCB","渣打银行");
        put("SCNX","四川农信");
        put("SDB","深发展");
        put("SDEB","顺德农商行");
        put("SDRCU","山东农信");
        put("SHINHAN","新韩银行");
        put("SHRB","上海华瑞银行");
        put("SJB","盛京银行");
        put("SNCCB","遂宁银行");
        put("SPDB","浦发银行");
        put("SRBANK","上饶银行");
        put("SRCB","上海农商银行");
        put("SUZB","苏州银行");
        put("SXNX","山西农信");
        put("SXXH","陕西信合");
        put("SZRCB","深圳农商银行");
        put("TACCB","泰安银行");
        put("TCRCB","太仓农商行");
        put("TJB","天津银行");
        put("TJBHB","天津滨海农商行");
        put("TRCB","天津农商");
        put("TZB","台州银行");
        put("UOB","大华银行");
        put("URB","联合村镇银行");
        put("WEB","微众银行");
        put("WFB","潍坊银行");
        put("WHB","威海商业银行");
        put("WHRC","武汉农商行");
        put("WJRCB","吴江农商行");
        put("WLMQB","乌鲁木齐银行");
        put("WRCB","无锡农商");
        put("WZB","温州银行");
        put("XAB","西安银行");
        put("XIB","厦门国际银行");
        put("XJRCCB","新疆农信银行");
        put("XMBANK","厦门银行");
        put("XTB","邢台银行");
        put("YKCB","营口沿海银行");
        put("YNRCCB","云南农信");
        put("YRRCB","黄河农商银行");
        put("YTB","烟台银行");
        put("ZJB","紫金农商银行");
        put("ZJLXRB","兰溪越商银行");
        put("ZJRCUB","浙江农信");
        put("ZJNX","浙江农信");
        put("ZJTLCB","浙江泰隆银行");
        put("ZRCB","张家港农商行");
        put("ZYB","中原银行");
        put("ZZB","郑州银行");
    }};



    /*
    校验过程：
    1、从卡号最后一位数字开始，逆向将奇数位(1、3、5等等)相加。
    2、从卡号最后一位数字开始，逆向将偶数位数字，先乘以2（如果乘积为两位数，将个位十位数字相加，即将其减去9），再求和。
    3、将奇数位总和加上偶数位总和，结果应该可以被10整除。
    */
    /**
     * 校验银行卡卡号
     */
    public  boolean checkBankCard(String bankCard) {
        if(bankCard.length() < 15 || bankCard.length() > 19) {
            return false;
        }
        char bit = getBankCardCheckCode(bankCard.substring(0, bankCard.length() - 1));
        if(bit == 'N'){
            return false;
        }
        return bankCard.charAt(bankCard.length() - 1) == bit;
    }

    public static void main(String[] args) {
        System.out.println( getBankNameByCardNo("6230195950060279658"));

    }


    /**
     * 获取银行名称
     * @param cardNo
     * @return
     */
    public String getBankNameByCardNo(String cardNo){
        String bankNameUrl="https://ccdcapi.alipay.com/validateAndCacheCardInfo.json?_input_charset=utf-8&cardNo="+cardNo+"&cardBinCheck=true";
        String result= HttpUtil.get(bankNameUrl);
        if(StrUtil.isBlank(result)){
            throw new GlobalRunTimeException("暂时不支持该银行卡绑定");
        }
        JSONObject jsonObject = JSONObject.parseObject(result);
        String bank = jsonObject.getString("bank");
        String cardType = jsonObject.getString("cardType");
        if(!"DC".equals(cardType)){
            throw new GlobalRunTimeException("暂时只支持储蓄卡绑定");
        }
        String name = bankMapRelation.get(bank);
        if(StrUtil.isBlank(name)){
            throw new GlobalRunTimeException("暂时不支持该银行卡绑定");
        }
        return name;
    }



    /**
     * 从不含校验位的银行卡卡号采用 Luhm 校验算法获得校验位
     * @param nonCheckCodeBankCard
     * @return
     */
    public  char getBankCardCheckCode(String nonCheckCodeBankCard){
        if(nonCheckCodeBankCard == null || nonCheckCodeBankCard.trim().length() == 0
                || !nonCheckCodeBankCard.matches("\\d+")) {
            //如果传的不是数据返回N
            return 'N';
        }
        char[] chs = nonCheckCodeBankCard.trim().toCharArray();
        int luhmSum = 0;
        for(int i = chs.length - 1, j = 0; i >= 0; i--, j++) {
            int k = chs[i] - '0';
            if(j % 2 == 0) {
                k *= 2;
                k = k / 10 + k % 10;
            }
            luhmSum += k;
        }
        return (luhmSum % 10 == 0) ? '0' : (char)((10 - luhmSum % 10) + '0');
    }

    public static boolean isValidBankCardNumber(String cardNumber) {
        // 如果银行卡号为空或长度小于16或大于19，则直接返回false
        if (cardNumber == null || cardNumber.length() < 16 || cardNumber.length() > 19) {
            return false;
        }

        // 如果银行卡号包含非数字字符，则也应该返回false
        if (!cardNumber.matches("\\d+")) {
            return false;
        }

        // 计算银行卡号的校验位
        // 将银行卡号转换为整型数组，从校验位前一位开始，依次对每一位数字乘以2（偶数位）或1（奇数位），然后将乘积的各位数字相加
        // 最后将所有位数相加得到校验和，校验和再减去个位数的值得到校验位，如果校验位为0，则该银行卡号是有效的
        int[] digits = new int[cardNumber.length()];
        for (int i = 0; i < cardNumber.length(); i++) {
            digits[i] = Integer.parseInt(String.valueOf(cardNumber.charAt(i)));
        }

        int sum = 0;
        boolean isEven = false;
        for (int i = digits.length - 2; i >= 0; i--) {
            int digit = digits[i];
            if (isEven) {
                digit *= 2;
                if (digit > 9) {
                    digit -= 9;
                }
            }
            sum += digit;
            isEven = !isEven;
        }

        int checkDigit = (10 - sum % 10) % 10;
        return checkDigit == digits[digits.length - 1];
    }



    public void checkFourPart(String bankCard,String identityNo,String mobile,String name){
        String host = "https://jumdres.market.alicloudapi.com";
        String path = "/bankcard/4-validate";
        String appCode = "4c0438be96ab42cdb08911fc01502a2c";
        String header = "APPCODE " + appCode;
        Map body = Maps.newHashMap();
        body.put("bankcard_number", bankCard);
        body.put("idcard_number", identityNo);
        body.put("mobile_number", mobile);
        body.put("name", name);
        HttpResponse response = HttpRequest.post(host+path).header(Header.AUTHORIZATION.getValue(),header).form(body).execute();
        JSONObject result = JSONObject.parseObject(response.body());
        if(StrUtil.equals(result.getString("code"),"200")){
            if(!StrUtil.equals(result.getJSONObject("data").getString("result"),"0")){
                throw new GlobalRunTimeException(ErrorCode.BANK_INFO_ERROR);
            }
        }else{
            throw new GlobalRunTimeException(result.getString("msg"));
        }
    }



    /**
     *身份证验证
     * @param idStr
     * @return
     */
    public boolean IdentityCardVerification(String idStr){
        String[] wf = { "1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2" };
        String[] checkCode = { "7", "9", "10", "5", "8", "4", "2", "1", "6", "3", "7", "9", "10", "5", "8", "4", "2" };
        String iDCardNo = "";
        try {
            //判断号码的长度 15位或18位
            if (idStr.length() != 15 && idStr.length() != 18) {
                return false;
            }
            if (idStr.length() == 18) {
                iDCardNo = idStr.substring(0, 17);
            } else if (idStr.length() == 15) {
                iDCardNo = idStr.substring(0, 6) + "19" + idStr.substring(6, 15);
            }
            if (isStrNum(iDCardNo) == false) {
                return false;
            }
            //判断出生年月
            String strYear = iDCardNo.substring(6, 10);// 年份
            String strMonth = iDCardNo.substring(10, 12);// 月份
            String strDay = iDCardNo.substring(12, 14);// 月份
            if (isStrDate(strYear + "-" + strMonth + "-" + strDay) == false) {
                return false;
            }
            GregorianCalendar gc = new GregorianCalendar();
            SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd");
            if ((gc.get(Calendar.YEAR) - Integer.parseInt(strYear)) > 150 || (gc.getTime().getTime() - s.parse(strYear + "-" + strMonth + "-" + strDay).getTime()) < 0) {
                return false;
            }
            if (Integer.parseInt(strMonth) > 12 || Integer.parseInt(strMonth) == 0) {
                return false;
            }
            if (Integer.parseInt(strDay) > 31 || Integer.parseInt(strDay) == 0) {
                return false;
            }
            //判断地区码
            Hashtable h = GetAreaCode();
            if (h.get(iDCardNo.substring(0, 2)) == null) {
                return false;
            }
            //判断最后一位
            int theLastOne = 0;
            for (int i = 0; i < 17; i++) {
                theLastOne = theLastOne + Integer.parseInt(String.valueOf(iDCardNo.charAt(i))) * Integer.parseInt(checkCode[i]);
            }
            int modValue = theLastOne % 11;
            String strVerifyCode = wf[modValue];
            iDCardNo = iDCardNo + strVerifyCode;
            if (idStr.length() == 18 &&!iDCardNo.equals(idStr)) {
                return false;
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return true;
    }

    /**
     * 地区代码
     * @return Hashtable
     */
    private static Hashtable GetAreaCode() {
        Hashtable hashtable = new Hashtable();
        hashtable.put("11", "北京");
        hashtable.put("12", "天津");
        hashtable.put("13", "河北");
        hashtable.put("14", "山西");
        hashtable.put("15", "内蒙古");
        hashtable.put("21", "辽宁");
        hashtable.put("22", "吉林");
        hashtable.put("23", "黑龙江");
        hashtable.put("31", "上海");
        hashtable.put("32", "江苏");
        hashtable.put("33", "浙江");
        hashtable.put("34", "安徽");
        hashtable.put("35", "福建");
        hashtable.put("36", "江西");
        hashtable.put("37", "山东");
        hashtable.put("41", "河南");
        hashtable.put("42", "湖北");
        hashtable.put("43", "湖南");
        hashtable.put("44", "广东");
        hashtable.put("45", "广西");
        hashtable.put("46", "海南");
        hashtable.put("50", "重庆");
        hashtable.put("51", "四川");
        hashtable.put("52", "贵州");
        hashtable.put("53", "云南");
        hashtable.put("54", "西藏");
        hashtable.put("61", "陕西");
        hashtable.put("62", "甘肃");
        hashtable.put("63", "青海");
        hashtable.put("64", "宁夏");
        hashtable.put("65", "新疆");
        hashtable.put("71", "台湾");
        hashtable.put("83", "台湾");
        hashtable.put("81", "香港");
        hashtable.put("82", "澳门");
        hashtable.put("83", "台湾");
        hashtable.put("91", "国外");
        return hashtable;
    }
    /**
     * 判断字符串是否为数字
     * @param str
     * @return
     */
    private static boolean isStrNum(String str) {
        Pattern pattern = Pattern.compile("[0-9]*");
        Matcher isNum = pattern.matcher(str);
        if (isNum.matches()) {
            return true;
        } else {
            return false;
        }
    }
    /**
     * 判断字符串是否为日期格式
     * @param strDate
     * @return
     */
    public static boolean isStrDate(String strDate) {
        Pattern pattern = Pattern.compile("^((\\d{2}(([02468][048])|([13579][26]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(\\s(((0?[0-9])|([1-2][0-3]))\\:([0-5]?[0-9])((\\s)|(\\:([0-5]?[0-9])))))?$");
        Matcher m = pattern.matcher(strDate);
        if (m.matches()) {
            return true;
        } else {
            return false;
        }
    }
}
